package team.hyznrj.studentsys.service.impl;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import team.hyznrj.studentsys.converter.ConductScore2ConductScoreDto;
import team.hyznrj.studentsys.converter.ConductScoreDto2ConductScore;
import team.hyznrj.studentsys.dao.mapper.ConductScoreMapper;
import team.hyznrj.studentsys.dao.repository.*;
import team.hyznrj.studentsys.dto.ConductScoreDto;
import team.hyznrj.studentsys.dto.ConductSummaryScoreDto;
import team.hyznrj.studentsys.dto.QualityMarkDto;
import team.hyznrj.studentsys.dto.SkillMarkDto;
import team.hyznrj.studentsys.entity.*;
import team.hyznrj.studentsys.entity.table.ScoreQualityTable;
import team.hyznrj.studentsys.entity.table.ScoreSkillTable;
import team.hyznrj.studentsys.form.ConductScoreConditionalForm;
import team.hyznrj.studentsys.service.ConductScoreService;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ReMidDream
 * @date 2018-04-02 19:20
 **/
@Service
public class ConductScoreServiceImpl implements ConductScoreService {

    @Autowired
    private ConductScoreMapper conductScoreMapper;
    @Autowired
    private ConductScore2ConductScoreDto conductScore2ConductScoreDto;
    @Autowired
    private ConductScoreDto2ConductScore conductScoreDto2ConductScore;
    @Autowired
    private OrganizeMarkRepository organizeMarkRepository;
    @Autowired
    private SpecialMarkRepository specialMarkRepository;
    @Autowired
    private ScienceMarkRepository scienceMarkRepository;
    @Autowired
    private ConductScoreRepository conductScoreRepository;
    @Autowired
    private ScoreSkillTableRepository scoreSkillTableRepository;
    @Autowired
    private ScoreQualityTableRepository scoreQualityTableRepository;
    @Autowired
    private MaxMarkRepository maxMarkRepository;

    @Override
    public List<ConductScoreDto> findByConductScoreConditionForm(ConductScoreConditionalForm conductScoreConditionalForm) {

        if(conductScoreConditionalForm.getStudentId() != null){
            String[] split = conductScoreConditionalForm.getStudentId().split(",");
            List<String> studentIds = Arrays.asList(split);
            conductScoreConditionalForm.setStudentIds(studentIds);
        }
        List<ConductScore> conductScoreList = conductScoreMapper.findByConductScoreConditionalForm(conductScoreConditionalForm);
        return  conductScore2ConductScoreDto.converter(conductScoreList);
    }

    @Override
    public List<ConductSummaryScoreDto> sumConductScore(List<ConductScoreDto> conductScoreDtos) {
        MaxMark maxMark = maxMarkRepository.findOne(1);
        return conductScoreDtos.stream().map(conductScoreDto -> {

            if (conductScoreDto.getScienceMark().getScienceMarkValue().compareTo(maxMark.getScienceMaxMark()) > 0) {
                conductScoreDto.getScienceMark().setScienceMarkValue(maxMark.getScienceMaxMark());
            }

            if (conductScoreDto.getOrganizeMark().getOrganizeMarkValue().compareTo(maxMark.getOrganizeMaxMark()) > 0) {
                conductScoreDto.getOrganizeMark().setOrganizeMarkValue(maxMark.getOrganizeMaxMark());
            }

            if (conductScoreDto.getSpecialMark().getSpecialMarkValue().compareTo(maxMark.getSpecialMaxMark()) > 0) {
                conductScoreDto.getSpecialMark().setSpecialMarkValue(maxMark.getSpecialMaxMark());
            }

            ConductSummaryScoreDto conductSummaryScoreDto = new ConductSummaryScoreDto(conductScoreDto.getScienceMark().getScienceMarkValue(),
                    conductScoreDto.getOrganizeMark().getOrganizeMarkValue(),conductScoreDto.getSpecialMark().getSpecialMarkValue());

            Optional<BigDecimal> qualityMark = conductScoreDto.getQualityMark().stream().map(QualityMarkDto::getMark).reduce(BigDecimal::add);
            Optional<BigDecimal> skillMark = conductScoreDto.getSkillMark().stream().map(SkillMarkDto::getMark).reduce(BigDecimal::add);

            if (qualityMark.get().compareTo(maxMark.getQualityMaxMark()) > 0) {
                conductSummaryScoreDto.setQualityMark(maxMark.getQualityMaxMark());
            }else {
                conductSummaryScoreDto.setQualityMark(qualityMark.get());
            }

            if (skillMark.get().compareTo(maxMark.getSkillMaxMark()) > 0) {
                conductSummaryScoreDto.setSkillMark(maxMark.getOrganizeMaxMark());
            }else {
                conductSummaryScoreDto.setSkillMark(skillMark.get());
            }

            BeanUtils.copyProperties(conductScoreDto,conductSummaryScoreDto);
            return conductSummaryScoreDto;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertOrUpdateConductScore(List<ConductScoreDto> conductScoreDto) {
        List<ConductScore> conductScores = conductScoreDto2ConductScore.converter(conductScoreDto);
        conductScoreRepository.save(conductScores);

        //插入,更新
        Set<OrganizeMark> organizeMarks = new HashSet<>();
        Set<ScienceMark> scienceMarks = new HashSet<>();
        Set<SpecialMark> specialMarks = new HashSet<>();
        Set<ScoreSkillTable> scoreSkillTables = new HashSet<>();
        Set<ScoreQualityTable> scoreQualityTables = new HashSet<>();

        //将各加分项打入list
        for (ConductScoreDto scoreDto : conductScoreDto) {
            organizeMarks.add(scoreDto.getOrganizeMark());
            scienceMarks.add(scoreDto.getScienceMark());
            specialMarks.add(scoreDto.getSpecialMark());

            for (SkillMarkDto skillMarkDto : scoreDto.getSkillMark()) {
                ScoreSkillTable scoreSkillTable = new ScoreSkillTable();
                scoreSkillTable.setConductScoreId(scoreDto.getId());
                scoreSkillTable.setSkillMarkId(skillMarkDto.getId());
                scoreSkillTable.setMark(skillMarkDto.getMark());
                scoreSkillTable.setRemark(skillMarkDto.getRemark());
                scoreSkillTables.add(scoreSkillTable);
            }

            for (QualityMarkDto qualityMarkDto : scoreDto.getQualityMark()) {
                ScoreQualityTable scoreQualityTable = new ScoreQualityTable();
                scoreQualityTable.setConductScoreId(scoreDto.getId());
                scoreQualityTable.setQualityMarkId(qualityMarkDto.getId());
                scoreQualityTable.setMark(qualityMarkDto.getMark());
                scoreQualityTable.setRemark(qualityMarkDto.getRemark());
                scoreQualityTables.add(scoreQualityTable);
            }

        }
        organizeMarkRepository.save(organizeMarks);
        scienceMarkRepository.save(scienceMarks);
        specialMarkRepository.save(specialMarks);
        scoreSkillTableRepository.save(scoreSkillTables);
        scoreQualityTableRepository.save(scoreQualityTables);
        return true;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean deleteConductScoreWithSetZero(String id) {
        if (StringUtils.isEmpty(id)) {
            return false;
        }
        if (conductScoreMapper.deleteSpecialMarkById(id)!=1) {
            throw new RuntimeException();
        }
        if (conductScoreMapper.deleteScienceMarkById(id)!=1) {
            throw new RuntimeException();
        }
        if (conductScoreMapper.deleteConductScoreById(id)!=1) {
            throw new RuntimeException();
        }
        if (conductScoreMapper.deleteOrganizeMarkById(id)!=1) {
            throw new RuntimeException();
        }
        if (conductScoreMapper.deleteScoreQualityTableById(id) <= 0) {
           throw new RuntimeException();
        }
        if (conductScoreMapper.deleteScoreSkillTableById(id)<= 0) {
            throw new RuntimeException();
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean deleteRealConductScore(String id) {
        if (StringUtils.isEmpty(id)) {
            return false;
        }
        try {
            organizeMarkRepository.delete(id);
            specialMarkRepository.delete(id);
            scienceMarkRepository.delete(id);
            conductScoreRepository.delete(id);
            scoreQualityTableRepository.delete(id);
            scoreSkillTableRepository.delete(id);
        } catch (RuntimeException e) {
            throw new RuntimeException();
        }
        return true;
    }


}
